package com.xmall.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xmall.bean.table.*;
import com.xmall.bean.vo.BaseCouponRespVO;
import com.xmall.bean.vo.CouponMallVO;
import com.xmall.bean.vo.CouponUserVO;
import com.xmall.bean.vo.CouponVO;
import com.xmall.mapper.*;
import com.xmall.service.CouponService;
import com.xmall.service.util.CouponUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class CouponServiceImpl implements CouponService {

    @Autowired
    CouponMapper couponMapper;

    @Autowired
    CouponUserMapper couponUserMapper;

    @Autowired
    CartMapper cartMapper;

    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    GrouponRulesMapper grouponRulesMapper;

    @Autowired
    GoodsMapper goodsMapper;

    @Override
    public Map<String, Object> queryList(Map<String, String> params) {
        PageHelper.startPage(Integer.parseInt(params.get("page")),Integer.parseInt(params.get("limit")));
        CouponExample couponExample = new CouponExample();
        couponExample.setOrderByClause(params.get("sort") + " " + params.get("order"));
        CouponExample.Criteria criteria = couponExample.createCriteria();

        if (params.get("name") != null){
            criteria.andNameLike("%" + params.get("name") +"%");
        }
        if (params.get("type") != null){
            criteria.andTypeEqualTo((short)Integer.parseInt(params.get("type")));
        }
        if (params.get("status") != null){
            criteria.andStatusEqualTo((short)Integer.parseInt(params.get("status")));
        }
        criteria.andDeletedEqualTo(false);
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        HashMap<String, Object> result = new HashMap<>();
        result.put("items",coupons);

        PageInfo<Coupon> couponPageInfo = new PageInfo<>(coupons);
        long total = couponPageInfo.getTotal();
        result.put("total",total);
        return result;

    }

    @Override
    public Coupon createCoupon(Coupon coupon) {
        // 如果type是2  则要生成8位 数字+大写字母 混合的兑换码
        if (coupon.getType() == 2){
            int length = 8;
            coupon.setCode(getRandomCode(length));
        }
        coupon.setAddTime(new Date());
        coupon.setUpdateTime(new Date());
        couponMapper.insertSelective(coupon);
        return coupon;
    }

    private String getRandomCode(int length) {
        String code = "";
        Random random = new Random();
        for (int i = 0; i <length ; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            if ("char".equals(charOrNum)){
                code += (char)(random.nextInt(26) + 65);
            }else {
                code += String.valueOf(random.nextInt(10));
            }
        }
        return code;
    }

    @Override
    public Coupon selectById(Integer id) {
        Coupon coupon = couponMapper.selectByPrimaryKey(id);
        return coupon;
    }

    @Override
    public Coupon updateCoupon(Coupon update) {
        update.setUpdateTime(new Date());
        couponMapper.updateByPrimaryKeySelective(update);
        return update;
    }

    @Override
    public void deleteCoupon(Coupon delete) {
        delete.setDeleted(true);
        //删除即下架
        delete.setStatus((short)2);
        updateCoupon(delete);
        //todo test
        //修改用户cskaoyanmall_coupon_user 的状态
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        criteria.andCouponIdEqualTo(delete.getId());
        CouponUser couponUser = new CouponUser();
        //使用状态, 如果是0则未使用；如果是1则已使用；如果是2则已过期；如果是3则已经下架；
        couponUser.setStatus((short)3);
        couponUserMapper.updateByExampleSelective(couponUser,couponUserExample);
    }

    @Override
    public Map<String, Object> queryListUser(Map<String, String> params) {
        PageHelper.startPage(Integer.parseInt(params.get("page")),Integer.parseInt(params.get("limit")));
        CouponUserExample coupon_userExample = new CouponUserExample();
        coupon_userExample.setOrderByClause(params.get("sort") + " " + params.get("order"));
        CouponUserExample.Criteria criteria = coupon_userExample.createCriteria();

        criteria.andCouponIdEqualTo(Integer.parseInt(params.get("couponId")));
        if (params.get("userId") != null){
            criteria.andUserIdEqualTo(Integer.parseInt(params.get("userId")));
        }

        if (params.get("status") != null){
            criteria.andStatusEqualTo((short)Integer.parseInt(params.get("status")));
        }
        List<CouponUser> coupon_users = couponUserMapper.selectByExample(coupon_userExample);
        PageInfo<CouponUser> coupon_userPageInfo = new PageInfo<>(coupon_users);
        long total = coupon_userPageInfo.getTotal();
        HashMap<String, Object> result = new HashMap<>();
        result.put("total",total);
        result.put("items",coupon_users);
        return result;
    }

    /**
     * ***************************************************************************************************
     *                                  微信小程序
     * ***************************************************************************************************
     */
    @Override
    public CouponVO<CouponMallVO> listMallCoupon(Integer page, Integer size) {
        List<CouponMallVO> couponMallVOS = new ArrayList<>();
        PageHelper.startPage(page, size);
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        criteria.andDeletedEqualTo(false);
        criteria.andStatusNotEqualTo((short)2);
        List<Coupon> couponList = couponMapper.selectByExample(couponExample);
        for (Coupon coupon : couponList) {
            couponMallVOS.add(new CouponMallVO(coupon.getId(),
                    coupon.getName(),
                    coupon.getDesc(),
                    coupon.getTag(),
                    coupon.getDiscount(),
                    coupon.getMin(),
                    coupon.getDays()));
        }
        return new CouponVO((int) new PageInfo<>(couponList).getTotal(), couponMallVOS);
    }

    @Override
    public CouponVO<CouponUserVO> listUserCoupon(Integer page, Integer size, Short status) {
        List<CouponUserVO> couponUserVOS = new ArrayList<>();
        PageHelper.startPage(page, size);
        CouponUserExample couponUserExample = new CouponUserExample();
        CouponUserExample.Criteria criteria = couponUserExample.createCriteria();
        criteria.andStatusEqualTo(status);
        criteria.andDeletedEqualTo(false);
        List<CouponUser> couponUserList = couponUserMapper.selectByExample(couponUserExample);
        for (CouponUser couponUser : couponUserList) {
            Coupon coupon = couponMapper.selectByPrimaryKey(couponUser.getCouponId());
            couponUserVOS.add(new CouponUserVO(couponUser.getId(),
                    coupon.getName(),
                    coupon.getDesc(),
                    coupon.getTag(),
                    coupon.getMin(),
                    coupon.getDiscount(),
                    coupon.getStartTime(),
                    coupon.getEndTime()));
        }
        return new CouponVO<>((int) new PageInfo<>(couponUserList).getTotal(), couponUserVOS);
    }

    @Override
    public List<CouponUserVO> listSelectiveCoupon(Integer cartId, Integer grouponRulesId) {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        Integer userId = user.getId();
        List<CouponUserVO> couponUserVOS = new ArrayList<>();
        CouponUserExample example = new CouponUserExample();
        CouponUserExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(user.getId());
        criteria.andStatusEqualTo((short)0);
        List<CouponUser> couponUsers = couponUserMapper.selectByExample(example);
        for (CouponUser couponUser : couponUsers) {
            Coupon coupon = couponMapper.selectByPrimaryKey(couponUser.getCouponId());
            if (CouponUtils.hasCoupon(cartId, coupon, cartMapper, goodsMapper, categoryMapper, userId)) {
                couponUserVOS.add(new CouponUserVO(couponUser.getId(),
                        coupon.getName(),
                        coupon.getDesc(),
                        coupon.getTag(),
                        coupon.getMin(),
                        coupon.getDiscount(),
                        coupon.getStartTime(),
                        coupon.getEndTime()));
            }
        }
        return couponUserVOS;
    }

    @Override
    public BaseCouponRespVO receiveCoupon(Map<String, Integer> map) {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        Integer userId = user.getId();
        Integer couponId = map.get("couponId");
        Coupon coupon = couponMapper.selectByPrimaryKey(couponId);
        Integer couponAmount = couponUserMapper.queryCouponAmountByCouponId(couponId);

        Integer statusCode = CouponUtils.InsertCoupon(coupon, couponAmount, couponUserMapper, userId, couponId, couponMapper);
        if (statusCode == 0) {
            return BaseCouponRespVO.ok("已成功领取优惠券！");
        }
        if (statusCode == 200) {
            return BaseCouponRespVO.fail("优惠券已领完！");
        }
        if (statusCode == 300) {
            return BaseCouponRespVO.fail("优惠券已经领取过!");
        }
        return BaseCouponRespVO.fail();
    }

    @Override
    public BaseCouponRespVO exchangeCoupon(Map<String, String> map) {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        Integer userId = user.getId();
        CouponExample couponExample = new CouponExample();
        CouponExample.Criteria criteria = couponExample.createCriteria();
        criteria.andCodeEqualTo(map.get("code"));
        criteria.andDeletedEqualTo(false);
        criteria.andTypeEqualTo((short)2);
        List<Coupon> coupons = couponMapper.selectByExample(couponExample);
        if (coupons.size() == 0) {
            return BaseCouponRespVO.errCode();
        }
        // TODO 一个优惠码只能兑换一张优惠券
        Coupon coupon = coupons.get(0);
        Integer couponId = coupon.getId();
        Integer couponAmount = couponUserMapper.queryCouponAmountByCouponId(couponId);
        if (couponAmount > 0) {
            return BaseCouponRespVO.fail("优惠码已兑换！");
        }
        Integer statusCode = CouponUtils.InsertCoupon(coupon, couponAmount, couponUserMapper, userId, couponId, couponMapper);
        return statusCode == 0 ? BaseCouponRespVO.ok("已成功兑换优惠券！") : BaseCouponRespVO.fail();
    }

}
